package com.atbeijing.dwpublisher.service.impl;

import com.atbeijing.constants.GmallConstants;
import com.atbeijing.dwpublisher.bean.Option;
import com.atbeijing.dwpublisher.bean.Stat;
import com.atbeijing.dwpublisher.mapper.DauMapper;
import com.atbeijing.dwpublisher.mapper.OrderMapper;
import com.atbeijing.dwpublisher.service.PublisherService;
import io.searchbox.client.JestClient;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import io.searchbox.core.search.aggregation.MetricAggregation;
import io.searchbox.core.search.aggregation.TermsAggregation;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class PublisherServiceIMPL implements PublisherService {

    @Autowired
    DauMapper dauMapper;

    @Autowired
    OrderMapper orderMapper;

    //es客户端
    @Autowired
    private JestClient jestClient;

    @Override
    public Integer getDauTotal(String date) {
        return dauMapper.selectDauTotal(date);
    }

    @Override
    public Map getDauHours(String date) {
        //从mapper层获取数据
        List<Map> list = dauMapper.selectDauTotalHourMap(date);

        //创建map集合存放结果数据
        HashMap<String, Long> result = new HashMap<>();

        for (Map map : list) {
            result.put((String) map.get("LH"), (Long) map.get("CT"));
        }

        return result;
    }

    @Override
    public Double getOrderAmountTotal(String date) {
        return orderMapper.selectOrderAmountTotal(date);
    }

    @Override
    public Map<String, Double> getOrderAmountHourMap(String date) {
        //获取数据
        List<Map> list = orderMapper.selectOrderAmountHourMap(date);

        //创建新的map用于结果数据
        HashMap<String, Double> result = new HashMap<>();

        //遍历list集合将老Map的数据转换结构存入新map
        for (Map map : list) {
            result.put((String) map.get("CREATE_HOUR"), (Double) map.get("SUM_AMOUNT"));
        }

        return result;
    }

    /**
     * 通过es灵活查询
     * @param date
     * @param startPage
     * @param size
     * @param keyword
     * @return
     */
    @Override
    public Map<String, Object> getSaleDetail(String date, Integer startPage, Integer size, String keyword) throws IOException {
        //组装es查询语句
        //最外层{}
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //bool对象
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        //全词匹配
        boolQueryBuilder.filter(new TermQueryBuilder("dt", date));
        //分词匹配
        // operator：表示被筛选字段(sku_name)如何匹配查询条件的分词,默认是or ,and 表示被查字段满足所有sku_name的分词
        boolQueryBuilder.must(new MatchQueryBuilder("sku_name", keyword).operator(MatchQueryBuilder.Operator.AND));
        searchSourceBuilder.query(boolQueryBuilder);

        //  性别聚合
        TermsBuilder genderAggs = AggregationBuilders.terms("groupby_user_gender").field("user_gender").size(2);
        searchSourceBuilder.aggregation(genderAggs);

        //  年龄聚合
        TermsBuilder ageAggs = AggregationBuilders.terms("groupby_user_age").field("user_age").size(100);
        searchSourceBuilder.aggregation(ageAggs);

        // 行号= （页面-1） * 每页行数
        searchSourceBuilder.from((startPage - 1) * size);
        searchSourceBuilder.size(size);

        System.out.println(""+searchSourceBuilder.toString());

        Search search = new Search.Builder(searchSourceBuilder.toString()).addIndex(GmallConstants.ES_INDEX_DETAIL_QUERY).addType("_doc").build();
        //执行查询
        SearchResult searchResult = jestClient.execute(search);

        //命中数据条数
        BigDecimal total = new BigDecimal(searchResult.getTotal());
        //获取数据详情
        ArrayList<Map> detail = new ArrayList<>();
        List<SearchResult.Hit<Map, Void>> hits = searchResult.getHits(Map.class);
        for (SearchResult.Hit<Map, Void> hit : hits) {
            detail.add(hit.source);
        }

        //获取年龄占比聚合组数据
        MetricAggregation ageAggregations = searchResult.getAggregations();
        TermsAggregation groupbyUserAge = ageAggregations.getTermsAggregation("groupby_user_age");
        List<TermsAggregation.Entry> ageBuckets = groupbyUserAge.getBuckets();
        //小于20岁人数
        BigDecimal low20Count = new BigDecimal(0);
        //大于等于30人数
        BigDecimal up30Count =  new BigDecimal(0);
        for (TermsAggregation.Entry ageBucket : ageBuckets) {
            if (Integer.parseInt(ageBucket.getKey())<20){
                low20Count.add(new BigDecimal(ageBucket.getCount()));
            }else if (Integer.parseInt(ageBucket.getKey())>=30){
                up30Count.add(new BigDecimal(ageBucket.getCount()));
            }
        }

        //获取小于20岁的年龄占比
        BigDecimal low20Ratio = low20Count.divide(total, 1, BigDecimal.ROUND_HALF_UP);

        //获取大于30岁的年龄占比
        BigDecimal up30Ratio = up30Count.divide(total, 1, BigDecimal.ROUND_HALF_UP);

        //20岁到30岁年龄占比
        BigDecimal b1 = new BigDecimal(1);
        BigDecimal up20AndLow30Ratio = b1.subtract(low20Ratio).subtract(up30Ratio);

        Option low20Opt = new Option("20岁以下", low20Ratio);
        Option up20AndLow30Opt = new Option("20岁到30岁", up20AndLow30Ratio);
        Option up30Opt = new Option("30岁及30岁以上", up30Ratio);

        //创建List集合用来存放年龄聚合组的对象
        ArrayList<Option> ageOptList = new ArrayList<>();
        ageOptList.add(low20Opt);
        ageOptList.add(up20AndLow30Opt);
        ageOptList.add(up30Opt);

        //获取性别占比聚合组数据
        TermsAggregation userGender = ageAggregations.getTermsAggregation("groupby_user_gender");
        List<TermsAggregation.Entry> genderbuckets = userGender.getBuckets();
        BigDecimal maleCount = new BigDecimal(0);
        for (TermsAggregation.Entry genderbucket : genderbuckets) {
            if ("M".equals(genderbucket.getKey())){
                maleCount.add(new BigDecimal(genderbucket.getCount()));
            }
        }
        //获取男生性别占比
        BigDecimal maleRatio = maleCount.divide(total, 1, BigDecimal.ROUND_HALF_UP);
        //获取女生性别占比
        BigDecimal femaleRatio = b1.subtract(maleRatio);

        Option maleOpt = new Option("男", maleRatio);
        Option femaleOpt = new Option("女", femaleRatio);

        //创建存放性别的list集合
        ArrayList<Option> genderList = new ArrayList<>();
        genderList.add(maleOpt);
        genderList.add(femaleOpt);

        //创建年龄的Stat对象
        Stat ageStat = new Stat(ageOptList, "用户年龄占比");

        //创建性别的Stat的对象
        Stat genderStat = new Stat(genderList, "用户性别占比");

        //创建存放Stat对象的list集合
        ArrayList<Stat> stats = new ArrayList<>();
        stats.add(ageStat);
        stats.add(genderStat);

        //创建Map集合用来存放结果数据
        HashMap<String, Object> result = new HashMap<>();
        result.put("total", total);
        result.put("stat", stats);
        result.put("detail", detail);
        return result;
    }


}
